package org.sjsu.freedoor.service;

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.sjsu.freedoor.model.Freedoor;
import org.sjsu.freedoor.model.OfferList;
import org.sjsu.freedoor.model.Good;
import org.sjsu.freedoor.model.GoodList;
import org.sjsu.freedoor.security.Securable;
import org.sjsu.freedoor.util.Utilities;

@Path("")
public class GoodsService {
	
	@GET
	@Path("goods")
	@Produces(MediaType.APPLICATION_JSON)
	public Response getGoods(@QueryParam("page") String page) {
		/*
		 * RETURN:  all goods currently stored in our database as JSON string
		 *          includes goods originating from our node and all replicated nodes
		 * EXAMPLE: 
		 *			{"goods":[ 
		 *			 {"community_url":"http://10.0.0.1", "id":"12345", "name":"gardening", "type":"goods", "description":"need help gardening", "status":"buying", "timestamp": "11/11/2012 13:59"},
		 *			 {"community_url":"http://10.0.0.1", "id":"12346", "name":"painting", "type":"goods", "description":"willing to paint your house", "status":"buying", "timestamp": "11/11/2012 13:59"},
		 *			 {"community_url":"http://10.0.0.2", "id":"12347", "name":"tutor needed", "type":"goods", "description":"looking for a math tutor", "status":"buying", "timestamp": "11/11/2012 13:59"}"
		 *			 ]}
		 */

		Freedoor fd = Freedoor.getInstance();
		
		GoodList goods;
		
		if(page == null || page.isEmpty() || Integer.parseInt(page) == 0)
			goods = fd.getGoods();
		else
			goods = fd.getGoods(Integer.parseInt(page));
		
		//goods.removeForeignGoods(Freedoor.SELF_URL);
		
		String msg = goods.toJsonString(true, true);
		System.out.println(msg);
		
		return Response.ok(goods.toJsonObject(), MediaType.TEXT_PLAIN).build();
	}
	
	@POST
	@Path("goods")
	@Produces(MediaType.TEXT_PLAIN)
	@Consumes(MediaType.APPLICATION_JSON)
	@Securable
	public Response postGoods(String body) {
		/*
		 * RETURN:  comma-separated list of keys for successfully committed goods
		 * EXAMPLE: AB8593EF11,4729FCC03E
		 * INPUT:   {"goods":[ 
		 *			 {"community_url":"http://10.0.0.1", "id":"12345", "name":"gardening", "type":"goods", "description":"need help gardening", "status":"buying", "timestamp": "11/11/2012 13:59"},
		 *			 {"community_url":"http://10.0.0.1", "id":"12346", "name":"painting", "type":"goods", "description":"willing to paint your house", "status":"buying", "timestamp": "11/11/2012 13:59"},
		 *			 {"community_url":"http://10.0.0.2", "id":"12347", "name":"tutor needed", "type":"goods", "description":"looking for a math tutor", "status":"buying", "timestamp": "11/11/2012 13:59"}
		 *			 ]}
		 */
		
		System.out.println(body);
		
		//return new goods id
		GoodList goodsToAdd = new GoodList();
		String resp = "";
		
		if(goodsToAdd.loadGoods(body)) {
			goodsToAdd.configureAllGoodsForNewLocalInsertion(Freedoor.SELF_URL);
			Freedoor fd = Freedoor.getInstance();
			resp = fd.insertOrUpdateGoods(goodsToAdd);
		}
		
		return Response.ok(resp, MediaType.TEXT_PLAIN).build();
	}
	
	@GET
	@Path("goods/{id}")
	@Produces(MediaType.APPLICATION_JSON)
	public Response getGoodWithID(@PathParam("id") String id) {
		/*
		 * RETURN:  good with key (MongoDB ObjectID) or NoContent if key doesn't exist
		 * EXAMPLE: {"community_url":"http://10.0.0.1", "id":"12345", "name":"gardening", "type":"goods", "description":"need help gardening", "status":"buying", "timestamp": "11/11/2012 13:59"}
		 * INPUT:   AB8593EF11
		 */
		
		System.out.println("get for id" + id);
		
		Freedoor fd = Freedoor.getInstance();
		Good good = fd.getGood(id);
		if ( good == null ) {
			return Response.noContent().build();
		} else {
			//return Response.ok(good.toJsonObject(), MediaType.TEXT_PLAIN).build();
			
			//change to doc format of {"goods":[...]} even though know to be one item
			GoodList lst = new GoodList();
			lst.add(good);
			return Response.ok(lst.toJsonObject(), MediaType.TEXT_PLAIN).build();
		}
	}
	
	@PUT
	@Path("goods/{id}")
	@Produces(MediaType.TEXT_PLAIN)
	@Consumes(MediaType.APPLICATION_JSON)
	@Securable
	public Response putGoodWithID(@PathParam("id") String id, String body) {
		/*
		 * RETURN:  Boolean status of update request, or NoContent if item doesn't exist
		 * EXAMPLE: TRUE
		 * INPUT:   {"goods":[ 
		 *			 {"community_url":"http://10.0.0.2", "id":"12347", "name":"tutor needed", "type":"goods", "description":"looking for a math tutor", "status":"buying", "timestamp": "11/11/2012 13:59"}
		 *			 ]}
		 *          Also accept non-array single JSON object
		 */
		
		String msg = "FALSE";
		
		GoodList goodToPut = new GoodList();
		
		if(goodToPut.loadGoods(body) && goodToPut.getList().size() > 0) {
			Good s = (Good)goodToPut.getList().toArray()[0];
			//updating local
			//TODO: these kinds of checks might need to be deeper
			if(s.getURL().isEmpty() || s.getURL().equals(Freedoor.SELF_URL)) {
				if(!s.getId().isEmpty() && !id.equals(s.getId())) //ID doesn't exist
					return Response.noContent().build();

				Freedoor fd = Freedoor.getInstance();
				msg = fd.updateGood(s);
			} else { //updating remote
				//TODO: not sure if should use existing or input URL for forwarding
				//forward request to remote server
				msg = Utilities.sendPutRequest(s.getURL(), s.toJsonObject());

				//return response
				Response.ok("Forwarded: " + msg, MediaType.TEXT_PLAIN).build();
			}
		}

		if(msg.equals(id)) //update successful
			msg = "TRUE";
		
		return Response.ok(msg, MediaType.TEXT_PLAIN).build();
	}
	
	@DELETE
	@Path("goods/{id}")
	@Produces(MediaType.TEXT_PLAIN)
	@Securable
	public Response deleteGoodWithID(@PathParam("id") String id) {
		/*
		 * RETURN:  Boolean status of update request, or NoContent if item doesn't exist
		 * EXAMPLE: TRUE
		 * INPUT:   None
		 */
		
		System.out.println("delete for id" + id);
		
		String msg = "FALSE";
		
		Freedoor fd = Freedoor.getInstance();
		Good g = fd.getGood(id);
		if(g == null)
			return Response.noContent().build();
		
		if(g.getURL().isEmpty() || g.getURL().equals(Freedoor.SELF_URL)) {
			Freedoor.RequestReturnType rtn = fd.removeService(id);
			if(rtn == Freedoor.RequestReturnType.IdNotFound) {
				return Response.noContent().build();
			} else if(rtn == Freedoor.RequestReturnType.Success) {
				msg = "TRUE";
			}
			
			return Response.ok(msg, MediaType.TEXT_PLAIN).build();
		} else { //updating remote
			//TODO: not sure if should use existing or input URL for forwarding
			//forward request to remote server
			msg = Utilities.sendDeleteRequest(g.getFullRestfulUri());

			//return response
			return Response.ok("Forwarded: " + msg, MediaType.TEXT_PLAIN).build();
		}
	}
	
	@GET
	@Path("goods/search")
	@Produces(MediaType.APPLICATION_JSON)
	public Response searchGoods(@QueryParam("name") String name, @QueryParam("status") String status, @QueryParam("page") String page) {
		/*
		 * RETURN:  all goods currently stored in our database that meet input search requirements
		 * 			Supported query parameters: name TODO: add more supported query parameters
		 *          includes goods originating from our node and all replicated nodes
		 *          results limited to 10 per page
		 * EXAMPLE: 
		 *			{"goods":[ 
		 *			 {"community_url":"http://10.0.0.1", "id":"12345", "name":"gardening", "type":"goods", "description":"need help gardening", "status":"buying", "timestamp": "11/11/2012 13:59"},
		 *			 {"community_url":"http://10.0.0.1", "id":"12346", "name":"painting", "type":"goods", "description":"willing to paint your house", "status":"buying", "timestamp": "11/11/2012 13:59"},
		 *			 {"community_url":"http://10.0.0.2", "id":"12347", "name":"tutor needed", "type":"goods", "description":"looking for a math tutor", "status":"buying", "timestamp": "11/11/2012 13:59"}"
		 *			 ]}
		 */
		
		if ( name == null ) {
			name = "";
		}
		if ( status == null ) {
			status = "";
		}
		
		System.out.println("searching for name: " + name);
		System.out.println("searching for status: " + status);
		System.out.println("page:" + page);
		

		Freedoor fd = Freedoor.getInstance();
		GoodList goods = null;
		
		if ( page == null || page.isEmpty() ) {
			if ( !name.equalsIgnoreCase("") && status.equalsIgnoreCase("")) {			//	Only name is specified.
				goods = fd.searchGoods(name, "", 0);
			} else if ( !status.equalsIgnoreCase("") && name.equalsIgnoreCase("") ) {	//	Only status is specified.
				if ( status.equalsIgnoreCase("buying") 	|| 
					 status.equalsIgnoreCase("buy") 	||	
					 status.equalsIgnoreCase("selling") ||
					 status.equalsIgnoreCase("sell") ) {
					goods = fd.searchGoods("", status, 0);
				}
			} else if ( !name.equalsIgnoreCase("") && !status.equalsIgnoreCase("") ) {	//	both name and status are specified.
				goods = fd.searchGoods(name, status, 0);
			} else if ( name.equalsIgnoreCase("") && status.equalsIgnoreCase("") ) {	//	none of name and status is specified.)
				goods = fd.searchGoods("", "", 0);
			}
		}		
		else {
			if ( !name.equalsIgnoreCase("") && status.equalsIgnoreCase("")) {			//	Only name is specified.
				goods = fd.searchGoods(name, "", Integer.parseInt(page));
			} else if ( !status.equalsIgnoreCase("") && name.equalsIgnoreCase("") ) {	//	Only status is specified.
				if ( status.equalsIgnoreCase("buying") 	|| 
					 status.equalsIgnoreCase("buy") 	||	
					 status.equalsIgnoreCase("selling") ||
					 status.equalsIgnoreCase("sell") ) {
					goods = fd.searchGoods("", status, Integer.parseInt(page));
				}
			} else if ( !name.equalsIgnoreCase("") && !status.equalsIgnoreCase("") ) {	//	both name and status are specified.
				goods = fd.searchGoods(name, status, Integer.parseInt(page));
			} else if ( name.equalsIgnoreCase("") && status.equalsIgnoreCase("") ) {	//	none of name and status is specified.)
				goods = fd.searchGoods("", "", Integer.parseInt(page));
			}
			
			
		}
		
		String msg = "";
		if (goods != null) {
			//goods.removeForeignGoods(Freedoor.SELF_URL);
			msg = goods.toJsonString(true, true);
			System.out.println(msg);
			return Response.ok(goods.toJsonObject(), MediaType.TEXT_PLAIN).build();
		}
		
		return Response.noContent().build();
	}
	
	@GET
	@Path("goods/{id}/offers")
	@Produces(MediaType.APPLICATION_JSON)
	@Securable
	public Response getOffersForGoodID(@PathParam("id") String oid) {
		/*
		 * RETURN:  all offers for input good, or NoContent if good doesn't exist
		 * EXAMPLE: 
		 *			{"offers":[ 
		 *			 {"message":"i want to buy your goods" , "email":"john@doe.com", "id":" http://anothernode/goods/12345"},"
		 *           {"message":"i want to buy your goods too" , "email":"jane@doe.com", "id":" http://anothernode/goods/12345"}"
		 *			 ]}
		 */
		System.out.println("get offers for id " + oid);
				
		Freedoor fd = Freedoor.getInstance();
		
		OfferList offers  = fd.getOffersForGood(oid);
		
		if(offers == null && fd.getGood(oid) == null)
			return Response.noContent().build();
		
		String msg = offers.toJsonString(true, true);
		System.out.println(msg);
		
		return Response.ok(offers.toJsonObject(), MediaType.TEXT_PLAIN).build();
	}

	@POST
	@Path("goods/{id}/offers")
	@Produces(MediaType.TEXT_PLAIN)
	@Consumes(MediaType.APPLICATION_JSON)
	public Response postOffersForGoodID(@PathParam("id") String oid, String body) {
		/*
		 * RETURN:  Boolean status or NoContent if good doens't exist
		 * EXAMPLE: AB8593EF11,4729FCC03E
		 * INPUT:   {"offers":[{"email":"fake@fake.com", "message":"I'd like to meet Tom Sawyer in exchange", "id":""}]}
		 */
		
		System.out.println("posting offer for id: " + oid);
		System.out.println(body);
		String msg = "FALSE";

		//TODO: for efficiency, see if good exists first
		OfferList offers = new OfferList();
		if(offers.loadOffers(body)) {
			Freedoor fd = Freedoor.getInstance();
			
			Good goodToAddTo = fd.getGood(oid);

			if(goodToAddTo == null)
				return Response.noContent().build();

			if(goodToAddTo.getURL().isEmpty() || goodToAddTo.getURL().equals(Freedoor.SELF_URL)) {
				msg = fd.putOffersForGood(oid, offers);
			} else {
				//forward request to remote server
				msg = Utilities.sendPutRequest(goodToAddTo.getURL(), goodToAddTo.toJsonObject());

				//return response
				return Response.ok("Forwarded: " + msg, MediaType.TEXT_PLAIN).build();
			}
		}
		
		return Response.ok(msg, MediaType.TEXT_PLAIN).build();
	}

}
